En este curso se van a abordar los principales usos de dos de las librerías de R más utilizadas para manipular y formatear datos (dplyr) y realizar figuras (ggplot2) mediante ejemplos sencillos, aumentando la dificultad y las funciones que aprenderéis a utilizar. A continuación se mostrarán algunas de las figuras complejas que sabrás realizar cuando termines este curso.
(Poner algunas figuras complejas: 1) volcano plot)
Para llevar a cabo este curso necesitarás utilizar las siguientes librerías:
library(dplyr) ## Work with dataframes
library(ggplot2) ## Making figures
library(DT) ## Interface tables
library(pasilla) #Bioconductor
library(reshape2) ## Transform data
library(tidyr) ## pivot functions
library(tibble) ## modern dataframes
library(ggrepel) ## geom text without overlap
library(ggpubr) ## Publication-ready ggplot themes
dplyr-ggplot2ggplot2 nos permite crear una gran diversidad de gráficos con una capacidad de personalización muy alta.
La creación de gráficos con ggplot2 funciona por capas, siendo esenciales 3 de ellas:
x e y y aquellas variables que van a determinar aspectos como el color (color), relleno (fill) o la transparencia (alpha).geom_ determinan el tipo de gráfico. Entre ellos, los tipos más frecuentes en bioinformática son:
geom_point(), geom_jitter())geom_line())geom_bar())geom_boxplot())geom_tile())Opcionalmente, distinguimos 3 capas adicionales que ayudan a personalizar un gráfico:
Vamos a ver un ejemplo de gráfico sencillo donde se usan todas estas capas. En este gráfico, cada punto representa la expresión de un gen en un paciente:
example_data_tidy %>% # Data
ggplot(aes(x = State, # Column containing x variable
y = Expression, # Column containing y variable
color = State)) + # Column color variable
geom_boxplot() + # Plot boxplot
geom_jitter(width = 0.1, alpha = 0.5, size = 1) + # Plot dots over the boxplot
facet_wrap(~Gene) + # One plot per gene
scale_x_discrete(name = "Patient status") + # Change x axis title
scale_y_continuous(name = "Gene expression") + # Change y axis title
scale_color_brewer(palette = "Set1") + # Change color palette
theme_pubr() + # Publication-ready theme
theme(axis.text = element_text(size = 10), # Change axis titles font size
legend.position = "none") # Hide color legend
Estamos representando 3 variables:
Por ello, necesitamos un data frame con la siguiente estructura, donde las tres variables mencionadas anteriormente tienen una columna propia y cada fila es una observación:
example_data_tidy %>% datatable()
Sin embargo, los datos de partida suelen tener una estructura más parecida a esta, donde los datos de expresión y la información de los pacientes vienen en tablas separadas (metadatos y datos):
State.example_metadata %>% datatable()
example_data %>% datatable()
Aquí entra en juego el preprocesamiento de datos con dplyr para transformar y combinar estas tablas:
En este tutorial vamos a ver distintas funciones para transformar tablas de datos con dplyr y cómo podemos ponerlas en un formato adecuado para ggplot2, así como generar gráficos de alta calidad con este paquete.
dplyrEn la mayoría de los casos, los datos que vamos a utilizar no suelen estar en el formato que nos interesa para utilizar ggplot2. Por ello se requieren de otras librerías que nos faciliten este trabajo de transformación de datos. La librería más potente para esto es dplyr.
dplyr(TO-DO: Explicar los pipes)
Esta librería tiene múltiples funcionalidades. Para hacer un análisis exploratorio de alguna de las más importantes, se usará una tabla con información clínica de muestras de sangre de lupus y donantes sanos.
# Leemos el fichero
datos_clinicos = read.delim("https://bioinformaticsgrx.es/wp-content/uploads/2020/02/Phenodata.txt")
# Hacemos algún cambio rápido
datos_clinicos[datos_clinicos$Neutrophil_percent == 0,"Neutrophil_percent"] <- NA
datos_clinicos[datos_clinicos$Lymphocyte_percent == 0,"Lymphocyte_percent"] <- NA
datatable(datos_clinicos)
select -> Filtrar columnas(TO-DO: Cambiar nombres de columnas con select)
## select:
# La fórmula %>% se utiliza para introducir el dataframe
datatable(datos_clinicos %>% select(Patient,State,Gender))
# También podemos poner la primera y última columna que queremos mantener
# usando la fórmula from:to
datatable(datos_clinicos %>% select(Patient:Race))
# Y podemos combinar ambas técnicas
datatable(datos_clinicos %>% select(Patient:Gender,Treatment))
# También podemos eliminar columnas
datatable(datos_clinicos %>% select(-State))
filter -> Filtrar filas en base a condiciones# Indicamos la condición que queremos
datatable(datos_clinicos %>% filter(State == "Healthy"))
# Pudiendo añadir varias
datatable(datos_clinicos %>% filter(State == "Healthy" & Gender == "F"))
# O complicando el filtrado como queramos
datatable(datos_clinicos %>% filter((State == "SLE" & Gender == "F") & (Neutrophil_percent > 50 | Lymphocyte_percent > 30)))
# Igualmente podemos añadir otras funciones con %>%
datatable(datos_clinicos %>% filter((State == "SLE" & Gender == "F") & (Neutrophil_percent > 50 | Lymphocyte_percent > 30)) %>% select(Patient))
mutate -> Crear una nueva columna# Podemos generar una nueva columna llamada NLR que sea resultado de dividir
# las variables Neutrophil_percent y Lymphocyte_percent
datatable(datos_clinicos %>% mutate(NLR = Neutrophil_percent / Lymphocyte_percent))
# Como para algunas muestras no tendremos datos de NLR, podemos fitrar las mismas
# como se ha explicado previamente
datatable(datos_clinicos %>% mutate(NLR = Neutrophil_percent / Lymphocyte_percent) %>% filter(!(is.na(NLR))))
# Una función especial es add_rownames, que permite convertir los nombres de las filas en una columna más
datatable(datos_clinicos %>% add_rownames("Samples"))
## Warning: `add_rownames()` is deprecated as of dplyr 1.0.0.
## Please use `tibble::rownames_to_column()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
pull -> Crear un vector desde un dataframe# Solo indicar la columna que se quiere convertir en vector
datos_clinicos %>% pull(Patient)
## [1] BAY-H377 BAY-H290 BAY-H303 BAY-H380 BAY-H306 BAY-H248 BAY-H304
## [8] BAY-H288 BAY-H305 BAY-H373 BAY-H243 BAY-H257 BAY-H276 BAY-H294
## [15] BAY-H217 BAY-H379 BAY-H281 BAY-H287 BAY-H275 BAY-H246 BAY-H285
## [22] BAY-H384 BAY-H277 BAY-H241 BAY-H218 BAY-H269 BAY-H217 BAY-H218
## [29] BAY-H288 BAY-H248 BAY-H306 BAY-H294 BAY-H303 BAY-H243 BAY-H1169
## [36] BAY-H079 BAY-H297 BAY-H276 BAY-H200 BAY-H284 BAY-H305 SLE-161
## [43] SLE-144 SLE-80 SLE-197 SLE-254 SLE-73 SLE-161 SLE-169
## [50] SLE-260 SLE-233 SLE-233 SLE-80 SLE-202 SLE-202 SLE-31
## [57] SLE-31 SLE-60 SLE-260 SLE-83 SLE-224 SLE-234 SLE-194
## [64] SLE-169 SLE-237 SLE-231 SLE-169 SLE-60 SLE-179 SLE-244
## [71] SLE-138 SLE-60 SLE-169 SLE-241 SLE-254 SLE-202 SLE-60
## [78] SLE-143 SLE-237 SLE-202 SLE-125 SLE-59 SLE-169 SLE-224
## [85] SLE-179 SLE-90 SLE-179 SLE-60 SLE-254 SLE-144 SLE-179
## [92] SLE-244 SLE-233 SLE-138 SLE-169 SLE-90 SLE-144 SLE-244
## [99] SLE-233 SLE-144 SLE-169 SLE-254 SLE-256 SLE-80 SLE-31
## [106] SLE-80 SLE-254 SLE-224 SLE-279 SLE-60 SLE-233 SLE-73
## [113] SLE-256 SLE-80 SLE-202 SLE-234 SLE-264 SLE-152 SLE-60
## [120] SLE-214 SLE-256 SLE-60 SLE-197 SLE-202 SLE-31 SLE-202
## [127] SLE-234 SLE-237 SLE-171 SLE-202 SLE-143 SLE-224 SLE-197
## [134] SLE-138 SLE-59 SLE-260 SLE-179 SLE-233 SLE-233 SLE-202
## [141] SLE-224 SLE-179 SLE-169 SLE-169 SLE-80 SLE-110 SLE-254
## [148] SLE-244 SLE-233 SLE-202 SLE-202 SLE-152 SLE-60 SLE-271
## [155] SLE-254 SLE-241 SLE-125 SLE-169 SLE-31 SLE-161 SLE-244
## [162] SLE-125 SLE-171 SLE-110 SLE-169 SLE-234 SLE-202 SLE-296
## [169] SLE-90 SLE-264 SLE-125 SLE-125 SLE-254 SLE-231 SLE-171
## [176] SLE-60 SLE-202 SLE-80 SLE-144 SLE-169 SLE-110 SLE-191
## [183] SLE-158 SLE-125 SLE-260 SLE-80 SLE-264 SLE-110 SLE-144
## [190] SLE-179 SLE-202 SLE-152 SLE-202 SLE-169 SLE-231 SLE-244
## [197] SLE-144 SLE-143 SLE-138 SLE-60 SLE-169 SLE-241 SLE-256
## [204] SLE-169 SLE-144 SLE-110 SLE-171 SLE-80 SLE-231 SLE-80
## [211] SLE-256 SLE-152 SLE-197 SLE-110 SLE-179 SLE-80 SLE-231
## [218] SLE-287 SLE-169 SLE-144 SLE-80 SLE-31 SLE-144 SLE-254
## [225] SLE-171 SLE-158 SLE-179 SLE-202 SLE-158 SLE-231 SLE-169
## [232] SLE-80 SLE-224 SLE-234 SLE-271 SLE-244 SLE-224 SLE-191
## [239] SLE-179 SLE-241 SLE-144 SLE-161 SLE-260 SLE-31 SLE-234
## [246] SLE-271 SLE-59 SLE-234 SLE-224 SLE-90 SLE-244 SLE-179
## [253] SLE-202 SLE-271 SLE-143 SLE-158 SLE-125 SLE-264 SLE-31
## [260] SLE-202 SLE-90 SLE-169 SLE-254 SLE-260 SLE-80 SLE-256
## [267] SLE-244 SLE-171 SLE-202 SLE-144 SLE-264 SLE-110 SLE-237
## [274] SLE-241 SLE-233 SLE-171 SLE-244 SLE-197 SLE-80 SLE-31
## [281] SLE-125 SLE-60 SLE-169 SLE-158 SLE-31 SLE-231 SLE-60
## [288] SLE-169 SLE-194 SLE-114 SLE-60 SLE-169 SLE-138 SLE-152
## [295] SLE-80 SLE-144 SLE-271 SLE-202 SLE-144 SLE-143 SLE-31
## [302] SLE-241 SLE-254 SLE-179 SLE-80 SLE-169 SLE-209 SLE-307
## [309] SLE-339 SLE-343 SLE-327 SLE-325 SLE-326 SLE-339 SLE-327
## [316] SLE-324 SLE-324 SLE-339 SLE-327 SLE-325 SLE-325 SLE-339
## [323] SLE-342 SLE-326 SLE-327 SLE-324 SLE-343 SLE-311 SLE-324
## [330] SLE-326 SLE-325 SLE-312 SLE-324 SLE-327 SLE-326 SLE-335
## [337] SLE-325 SLE-324 SLE-339 SLE-311 SLE-327 SLE-325 SLE-311
## [344] SLE-325 SLE-324 SLE-325 SLE-344 BAY-H241 BAY-H288 BAY-H273
## [351] BAY-H285 BAY-H162 BAY-H275 BAY-H222 BAY-H287 BAY-H246 BAY-H282
## [358] BAY-H281 BAY-H277 BAY-H384 BAY-H235 BAY-H206 BAY-H164 BAY-H230
## [365] BAY-H379 BAY-H380 BAY-H377 BAY-H304 BAY-H254 BAY-H134 BAY-H160
## [372] BAY-H255 BAY-H231 BAY-H199 BAY-H257 BAY-H290 BAY-H344 BAY-H373
## [379] SLE-34 SLE-87 SLE-129 SLE-192 SLE-172 SLE-189 SLE-99
## [386] SLE-155 SLE-168 SLE-212 SLE-192 SLE-79 SLE-121 SLE-242
## [393] SLE-184 SLE-40 SLE-168 SLE-95 SLE-155 SLE-40 SLE-170
## [400] SLE-188 SLE-79 SLE-218 SLE-170 SLE-242 SLE-99 SLE-230
## [407] SLE-20 SLE-216 SLE-213 SLE-225 SLE-200 SLE-181 SLE-155
## [414] SLE-121 SLE-163 SLE-172 SLE-225 SLE-78 SLE-18 SLE-175
## [421] SLE-128 SLE-128 SLE-121 SLE-180 SLE-210 SLE-40 SLE-172
## [428] SLE-207 SLE-34 SLE-19 SLE-249 SLE-172 SLE-78 SLE-133
## [435] SLE-147 SLE-242 SLE-281 SLE-175 SLE-79 SLE-188 SLE-201
## [442] SLE-225 SLE-213 SLE-199 SLE-201 SLE-55 SLE-78 SLE-199
## [449] SLE-252 SLE-245 SLE-155 SLE-218 SLE-136 SLE-123 SLE-268
## [456] SLE-213 SLE-267 SLE-210 SLE-175 SLE-211 SLE-255 SLE-79
## [463] SLE-245 SLE-184 SLE-187 SLE-141 SLE-212 SLE-200 SLE-170
## [470] SLE-133 SLE-175 SLE-133 SLE-182 SLE-218 SLE-155 SLE-212
## [477] SLE-200 SLE-40 SLE-222 SLE-178 SLE-121 SLE-255 SLE-175
## [484] SLE-34 SLE-189 SLE-192 SLE-78 SLE-200 SLE-65 SLE-225
## [491] SLE-183 SLE-55 SLE-176 SLE-249 SLE-225 SLE-166 SLE-34
## [498] SLE-40 SLE-175 SLE-199 SLE-201 SLE-65 SLE-177 SLE-95
## [505] SLE-160 SLE-178 SLE-225 SLE-123 SLE-225 SLE-65 SLE-142
## [512] SLE-20 SLE-147 SLE-182 SLE-155 SLE-19 SLE-188 SLE-170
## [519] SLE-207 SLE-182 SLE-150 SLE-55 SLE-210 SLE-181 SLE-211
## [526] SLE-65 SLE-252 SLE-78 SLE-133 SLE-141 SLE-201 SLE-180
## [533] SLE-180 SLE-175 SLE-150 SLE-78 SLE-55 SLE-188 SLE-95
## [540] SLE-128 SLE-192 SLE-189 SLE-166 SLE-216 SLE-78 SLE-199
## [547] SLE-157 SLE-79 SLE-78 SLE-142 SLE-180 SLE-229 SLE-141
## [554] SLE-212 SLE-177 SLE-121 SLE-175 SLE-121 SLE-123 SLE-190
## [561] SLE-129 SLE-40 SLE-199 SLE-266 SLE-163 SLE-128 SLE-192
## [568] SLE-65 SLE-154 SLE-184 SLE-79 SLE-242 SLE-21 SLE-212
## [575] SLE-189 SLE-184 SLE-141 SLE-183 SLE-79 SLE-121 SLE-157
## [582] SLE-65 SLE-141 SLE-218 SLE-34 SLE-65 SLE-293 SLE-212
## [589] SLE-242 SLE-155 SLE-121 SLE-99 SLE-65 SLE-225 SLE-121
## [596] SLE-189 SLE-168 SLE-176 SLE-55 SLE-79 SLE-183 SLE-225
## [603] SLE-181 SLE-242 SLE-178 SLE-268 SLE-266 SLE-78 SLE-121
## [610] SLE-188 SLE-163 SLE-189 SLE-78 SLE-99 SLE-183 SLE-163
## [617] SLE-181 SLE-65 SLE-105 SLE-65 SLE-19 SLE-189 SLE-212
## [624] SLE-225 SLE-181 SLE-200 SLE-121 SLE-133 SLE-200 SLE-78
## [631] SLE-170 SLE-172 SLE-201 SLE-212 SLE-178 SLE-123 SLE-178
## [638] SLE-141 SLE-213 SLE-180 SLE-40 SLE-21 SLE-201 SLE-182
## [645] SLE-141 SLE-182 SLE-40 SLE-128 SLE-95 SLE-225 SLE-183
## [652] SLE-170 SLE-200 SLE-34 SLE-211 SLE-172 SLE-188 SLE-189
## [659] SLE-79 SLE-134 SLE-281 SLE-163 SLE-181 SLE-182 SLE-177
## [666] SLE-213 SLE-155 SLE-245 SLE-199 SLE-78 SLE-79 SLE-183
## [673] SLE-252 SLE-218 SLE-176 SLE-219 SLE-34 SLE-190 SLE-154
## [680] SLE-79 SLE-163 SLE-182 SLE-184 SLE-183 SLE-230 SLE-55
## [687] SLE-136 SLE-133 SLE-121 SLE-184 SLE-199 SLE-141 SLE-218
## [694] SLE-21 SLE-79 SLE-95 SLE-182 SLE-87 SLE-34 SLE-175
## [701] SLE-134 SLE-183 SLE-176 SLE-121 SLE-163 SLE-180 SLE-79
## [708] SLE-172 SLE-170 SLE-65 SLE-163 SLE-188 SLE-176 SLE-155
## [715] SLE-141 SLE-65 SLE-40 SLE-155 SLE-55 SLE-199 SLE-199
## [722] SLE-225 SLE-181 SLE-79 SLE-181 SLE-199 SLE-225 SLE-141
## [729] SLE-175 SLE-142 SLE-189 SLE-34 SLE-34 SLE-168 SLE-206
## [736] SLE-176 SLE-123 SLE-219 SLE-199 SLE-133 SLE-216 SLE-216
## [743] SLE-188 SLE-65 SLE-105 SLE-199 SLE-172 SLE-166 SLE-211
## [750] SLE-176 SLE-78 SLE-189 SLE-267 SLE-95 SLE-242 SLE-78
## [757] SLE-213 SLE-55 SLE-176 SLE-79 SLE-245 SLE-55 SLE-55
## [764] SLE-121 SLE-182 SLE-95 SLE-188 SLE-99 SLE-230 SLE-177
## [771] SLE-21 SLE-150 SLE-105 SLE-225 SLE-154 SLE-213 SLE-206
## [778] SLE-150 SLE-293 SLE-183 SLE-55 SLE-176 SLE-252 SLE-172
## [785] SLE-176 SLE-201 SLE-219 SLE-172 SLE-218 SLE-172 SLE-242
## [792] SLE-89 SLE-210 SLE-219 SLE-199 SLE-210 SLE-155 SLE-40
## [799] SLE-187 SLE-99 SLE-129 SLE-178 SLE-40 SLE-267 SLE-199
## [806] SLE-281 SLE-150 SLE-168 SLE-192 SLE-136 SLE-21 SLE-189
## [813] SLE-189 SLE-166 SLE-20 SLE-229 SLE-213 SLE-129 SLE-218
## [820] SLE-163 SLE-200 SLE-79 SLE-79 SLE-210 SLE-55 SLE-255
## [827] SLE-20 SLE-200 SLE-155 SLE-170 SLE-155 SLE-20 SLE-128
## [834] SLE-200 SLE-229 SLE-245 SLE-79 SLE-269 SLE-99 SLE-132
## [841] SLE-147 SLE-40 SLE-199 SLE-121 SLE-172 SLE-175 SLE-170
## [848] SLE-267 SLE-188 SLE-172 SLE-87 SLE-199 SLE-277 SLE-99
## [855] SLE-79 SLE-34 SLE-201 SLE-188 SLE-123 SLE-242 SLE-178
## [862] SLE-157 SLE-78 SLE-154 SLE-199 SLE-105 SLE-136 SLE-187
## [869] SLE-128 SLE-281 SLE-129 SLE-55 SLE-34 SLE-79 SLE-281
## [876] SLE-141 SLE-34 SLE-79 SLE-121 SLE-105 SLE-155 SLE-211
## [883] SLE-78 SLE-181 SLE-123 SLE-201 SLE-166 SLE-176 SLE-129
## [890] SLE-129 SLE-172 SLE-132 SLE-189 SLE-128 SLE-178 SLE-40
## [897] SLE-40 SLE-213 SLE-20 SLE-201 SLE-199 SLE-200 SLE-141
## [904] SLE-199 SLE-170 SLE-252 SLE-172 SLE-78 SLE-176 SLE-230
## [911] SLE-183 SLE-225 SLE-201 SLE-189 SLE-172 SLE-268 SLE-212
## [918] SLE-189 SLE-319 SLE-308 SLE-313 SLE-336 SLE-328 SLE-331
## [925] SLE-304 SLE-316 SLE-320 SLE-341 SLE-346 SLE-321 SLE-328
## [932] SLE-323 SLE-331 SLE-337 SLE-352 SLE-321 SLE-333 SLE-341
## [939] SLE-304 SLE-331 SLE-321 SLE-316 SLE-321 SLE-348 SLE-347
## [946] SLE-305 SLE-323 SLE-348 SLE-304 SLE-304 SLE-317 SLE-308
## [953] SLE-331 SLE-338 SLE-332 SLE-331 SLE-313 SLE-308 SLE-350
## [960] SLE-336 SLE-308 SLE-347 SLE-304 SLE-304 SLE-304 SLE-316
## [967] SLE-313 SLE-308 SLE-337 SLE-331 SLE-332 SLE-333 SLE-337
## [974] SLE-313 SLE-349 SLE-322 SLE-345 SLE-346 SLE-308 SLE-334
## [981] SLE-333 SLE-304 SLE-340 SLE-313 SLE-319 SLE-340 SLE-340
## [988] SLE-337 SLE-341 SLE-321 SLE-321 SLE-321 SLE-323 SLE-334
## [995] SLE-321 SLE-313
## 204 Levels: BAY-H079 BAY-H1169 BAY-H134 BAY-H160 BAY-H162 BAY-H164 ... SLE-99
group_by -> Agrupar en base a una condición# Esta función por si sola no produce ningún cambio, sino que se utiliza para
# indicar a funciones posteriores que todo lo que se haga se hará
# separarando los diferentes grupos de la variable que se indique
datatable(datos_clinicos %>% group_by(Gender))
summarize -> Estadísiticas de los datos#Queremos saber la media de SLEDAI de las muestras
datos_clinicos %>% summarize(Mean_SLEDAI = mean(SLEDAI,na.rm = T))
## Mean_SLEDAI
## 1 5.940763
# Como se ha indicado previamente, podemos agrupar los datos usando la función group_by
datos_clinicos %>% group_by(Gender) %>% summarize(Mean_SLEDAI = mean(SLEDAI,na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 2 x 2
## Gender Mean_SLEDAI
## <fct> <dbl>
## 1 F 6.05
## 2 M 5.14
datos_clinicos %>% group_by(State) %>% summarize(Max_SLEDAI = max(SLEDAI,na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 2 x 2
## State Max_SLEDAI
## <fct> <int>
## 1 Healthy 0
## 2 SLE 35
datos_clinicos %>% group_by(Race) %>% summarize(SD_SLEDAI = sd(SLEDAI,na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 4 x 2
## Race SD_SLEDAI
## <fct> <dbl>
## 1 AA 6.97
## 2 AS 0
## 3 C 4.50
## 4 H 5.09
arrange -> Ordenar una columna# De menor a mayor
datatable(datos_clinicos %>% arrange(SLEDAI))
# De mayor a menor
datatable(datos_clinicos %>% arrange(desc(SLEDAI)))
# O estableciendo el orden manualmente
datatable(datos_clinicos %>% arrange(factor(Gender, levels = c("M","F"))))
count -> Contar el número de filas de cada factor de una columna# Podemos ver cuantas filas hay de cada State
datos_clinicos %>% count(State)
## State n
## 1 Healthy 72
## 2 SLE 924
# Y agrupar por Gender
datos_clinicos %>% group_by(Gender) %>% count(State)
## # A tibble: 4 x 3
## # Groups: Gender [2]
## Gender State n
## <fct> <fct> <int>
## 1 F Healthy 57
## 2 F SLE 817
## 3 M Healthy 15
## 4 M SLE 107
A continuación harmeos un pipe más complejo de los vistos hasta ahora, para ver el potencial que podemos sacarle a dplyr.
datos_clinicos %>%
# Creamos la columna NLR
mutate(NLR = Neutrophil_percent / Lymphocyte_percent) %>%
# Filtramos para quedarnos solo con lupus y sin NA en NLR
filter(!(is.na(NLR)) & State == "SLE") %>%
# Agrupamos por paciente. Cada paciente tiene una o varias visitas
group_by(Patient) %>%
# Quedándonos con los pacientes con más de 3 visitas
filter(n() > 3) %>%
# Y vemos cuantas visitas de cada paciente están por debajo o por encima de los valores normales de NLR
count(NLR < 0.78 | NLR > 3.53)
## # A tibble: 150 x 3
## # Groups: Patient [83]
## Patient `NLR < 0.78 | NLR > 3.53` n
## <fct> <lgl> <int>
## 1 SLE-105 FALSE 5
## 2 SLE-110 FALSE 5
## 3 SLE-110 TRUE 2
## 4 SLE-121 FALSE 10
## 5 SLE-121 TRUE 5
## 6 SLE-123 FALSE 6
## 7 SLE-123 TRUE 1
## 8 SLE-125 FALSE 8
## 9 SLE-128 FALSE 4
## 10 SLE-128 TRUE 4
## # … with 140 more rows
dplyr también nos da la posibilidad de combinar varias tablas de forma similar a como se hacen consultas en bases de datos. Para mostrar estas funciones seguiremos usando la base de datos clínicos de pacientes de lupus. La otra tabla que vamos a usar es una tabla de expresión de genes ficticia, con el fin de que no sea muy costoso computacionalmente
# Añadir los rownames como columna llamada Samples
datos_clinicos <- datos_clinicos %>% add_rownames("Samples")
#Quedarnos con las 6 primeras muestras de lupus con NLR válido
muestras_lupus = datos_clinicos %>%
mutate(NLR = Neutrophil_percent / Lymphocyte_percent) %>%
filter(!(is.na(NLR)) & State == "SLE") %>%
select(Samples) %>%
head() %>%
pull()
#Quedarnos con las 6 primeras muestras de sanos
muestras_sano = datos_clinicos %>%
filter(State == "Healthy") %>%
select(Samples) %>%
head() %>%
pull()
# Crear la tabla
gene_expression = data.frame(Genes = rep(paste0("Gene",seq(1,10)), c(rep(12,10))),
Samples = rep(c(muestras_lupus,muestras_sano),10),
Values = rnorm(120))
datatable(gene_expression)
Las funciones principales para combinar dataframes son: inner_join, left_join / right_join, full_join
## Inner join: MATCH IN BOTH TABLES
datatable(gene_expression %>% inner_join(datos_clinicos,by="Samples"))
## Left join: prioritizes left table
datatable(gene_expression %>% left_join(datos_clinicos,by="Samples"))
datatable(datos_clinicos %>% left_join(gene_expression,by="Samples"))
datatable(gene_expression %>% right_join(datos_clinicos,by="Samples"))
datatable(datos_clinicos %>% right_join(gene_expression,by="Samples"))
datatable(gene_expression %>% full_join(datos_clinicos,by="Samples"))
(TO-DO: Join por columnas con distinto nombre)
A continuación vamos a preparar la tabla que vamos a usar para generar los gráficos en ggplot2. Para ello seguiremos usando los datos clínicos y las 12 muestras elegidas previamente, pero en este caso vamos a utilizar los datos reales de expresión de genes. Para evitar que nos lleve mucho tiempo, hemos preparado una matriz de expresión de 1000 genes
# Descargar la matriz de expresión
exp_data = read.delim("https://bioinformaticsgrx.es/wp-content/uploads/2022/03/expr.txt")
dim(exp_data)
## [1] 1000 996
# Para pasar la matriz a un formato que nos sirva para ggplot2 usamos la librería reshape2
# y dplyr
gene_expression = as.data.frame(exp_data) %>%
rownames_to_column(var = "Genes") %>%
pivot_longer(cols = datos_clinicos$Samples,names_to = "Samples",values_to = "Values") %>%
filter(Samples %in% c(muestras_lupus,muestras_sano)) %>%
inner_join(datos_clinicos,by="Samples")
datatable(gene_expression)
## Warning in instance$preRenderHook(instance): It seems your data is too big
## for client-side DataTables. You may consider server-side processing: https://
## rstudio.github.io/DT/server.html
ggplot2# Generar un diagrama de cajas (boxplot)
ggplot(data = gene_expression,aes(x=Samples,y=Values))+ # Con la función ggplot indicamos el dataframe que queremos usar, así como las columnas que se quieren usar en los ejes x e y
geom_boxplot() # La función geom_boxplot se usa para generar el diagrama de cajas
# Si en vez de un diagrama de cajas quisiéramos generar un gráfico de tipo violín, solo cambiamos la función geom_boxplot por geom_violin
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()
Como es lógico, estas figuras no quedan bien. Por ejemplo, los nombres de las muestras se sobrelapan, el color del fondo puede no gustarnos etc. Para modificar los aspectos estéticos de las figuras usaremos la función theme.
theme -> Modificar la apariencia(TO-DO: Hablar de ggpubr)
En primer lugar vamos a comentar las diferentes temáticas que existen por defecto en ggplot2. Como se verá a continuación, cada temática cambia varios elementos del gráfico como el color de fondo o el color de los ejes
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme_classic()
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme_bw()
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme_dark()
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme_light()
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme_minimal()
Sin embargo en la mayoría de los casos querremos establecer nuestro propio diseño. Si miramos la ayuda de la función theme, veremos muchísimos parámetros que podemos modificar.
Por ejemplo, si queremos cambiar el tamaño del texto lo podemos hacer de así
# Para modificar el texto debemos usar la función element_text
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme(text = element_text(size = 20)) # Para cambiar todo el texto
# Si solo queremos cambiar el texto del título de los ejes usamos el parametro axis.title
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme(axis.title = element_text(size = 20,color = "red")) # También podemos añadir color
# Y si lo que queremos es modificar los valores de los ejes, usamos la función axis.text
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
# usamos axis.text.x para cambiar solo el eje x
theme(axis.text.x = element_text(size = 20,color = "red"))
# El propósito de ver todo esto era evitar que los nombres se mezclen.
# Una buena solución es ponerlas en vertical, modificando el ángulo
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
#vjust para alinear el nombre en el centro
theme(axis.text.x = element_text(angle = 90,vjust = 0.5))
Igualmente podemos modificar los ejes del gráfico para cambiar el color o quitarlos
# Para modificar ambos usamos la función axis.line con la función element_line
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme(axis.text.x = element_text(angle = 90,vjust = 0.5),
axis.line = element_line(colour = "black"))
# Si queremos modificar alguno específicamente, lo indicamos
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme(axis.text.x = element_text(angle = 90,vjust = 0.5),
axis.line.x = element_line(colour = "blue"))
Y finalmente podemos cambiar el fondo de la gráfica
# Para modificar el fondo, usamos el parámetro panel.background con la función element_rect
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme(axis.text.x = element_text(angle = 90,vjust = 0.5),
axis.line = element_line(colour = "black"),
panel.background = element_rect(fill = "blue"))
# Si queremos controlar las rejillar usamos los parámetros panel.grid.major y panel.grid.minor
# con la función element_line
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme(axis.text.x = element_text(angle = 90,vjust = 0.5),
axis.line = element_line(colour = "black"),
panel.background = element_rect(fill = "white"),
panel.grid.major = element_line(colour = "purple"),
panel.grid.minor = element_line(colour = "orange"))
# Si no queremos que ningo de estos elementos aparezca
# usamos la función element_blank
ggplot(data = gene_expression,aes(x=Samples,y=Values))+
geom_violin()+
theme(axis.text.x = element_text(angle = 90,vjust = 0.5),
axis.line = element_line(colour = "black"),
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank())
Por supuesto, con la cantidad de parámetros que se incluyen en la función theme hay muchas más cosas que se pueden modificar. Algunos de ellos los veremos en las siguientes secciones, principalmente aquellas relacionadas con la leyenda.
sessionInfo()
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
##
## locale:
## [1] LC_CTYPE=en_GB.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=es_ES.UTF-8 LC_COLLATE=en_GB.UTF-8
## [5] LC_MONETARY=es_ES.UTF-8 LC_MESSAGES=en_GB.UTF-8
## [7] LC_PAPER=es_ES.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=es_ES.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggpubr_0.2.5 magrittr_1.5 ggrepel_0.8.2 tibble_3.0.0 tidyr_1.0.2
## [6] reshape2_1.4.3 pasilla_1.14.0 DT_0.13 ggplot2_3.3.5 dplyr_1.0.2
##
## loaded via a namespace (and not attached):
## [1] Rcpp_1.0.4 RColorBrewer_1.1-2 pillar_1.4.3
## [4] compiler_3.6.3 plyr_1.8.6 tools_3.6.3
## [7] digest_0.6.26 jsonlite_1.7.1 evaluate_0.14
## [10] lifecycle_0.2.0 gtable_0.3.0 pkgconfig_2.0.3
## [13] rlang_1.0.0 cli_3.1.1 rstudioapi_0.11
## [16] crosstalk_1.1.0.1 yaml_2.2.1 xfun_0.23
## [19] withr_2.1.2 stringr_1.4.0 knitr_1.28
## [22] generics_0.0.2 vctrs_0.3.8 htmlwidgets_1.5.1
## [25] grid_3.6.3 tidyselect_1.1.0 glue_1.6.1
## [28] R6_2.4.1 fansi_0.4.1 rmarkdown_2.5.3
## [31] farver_2.0.3 purrr_0.3.3 scales_1.1.0
## [34] ellipsis_0.3.2 htmltools_0.5.0.9001 colorspace_1.4-1
## [37] ggsignif_0.6.0 labeling_0.3 utf8_1.1.4
## [40] stringi_1.4.6 munsell_0.5.0 crayon_1.3.4